From e9ee842db1cec299f6b67ecfa9eb23985d60aad3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 4 Dec 2008 20:18:02 +0100 Subject: [PATCH] Move drawable clip tracking into GdkGC --- gdk/gdkgc.c | 91 ++++++++++++++++++++++++++++++++++------------ gdk/gdkinternals.h | 11 +++--- gdk/gdkwindow.c | 71 +++++++++++++++++++----------------- gdk/gdkwindow.h | 1 + 4 files changed, 112 insertions(+), 62 deletions(-) diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c index 6bc3a994ce..355a346132 100644 --- a/gdk/gdkgc.c +++ b/gdk/gdkgc.c @@ -43,6 +43,10 @@ struct _GdkGCPrivate { GdkRegion *clip_region; + guint32 region_tag_applied; + + GdkRegion *old_clip_region; + GdkSubwindowMode subwindow_mode; GdkFill fill; @@ -190,6 +194,8 @@ gdk_gc_finalize (GObject *object) if (priv->clip_region) gdk_region_destroy (priv->clip_region); + if (priv->old_clip_region) + gdk_region_destroy (priv->old_clip_region); if (gc->colormap) g_object_unref (gc->colormap); if (priv->tile) @@ -273,6 +279,12 @@ gdk_gc_set_values (GdkGC *gc, priv = GDK_GC_GET_PRIVATE (gc); + if ((values_mask & GDK_GC_CLIP_X_ORIGIN) || + (values_mask & GDK_GC_CLIP_Y_ORIGIN) || + (values_mask & GDK_GC_CLIP_MASK) || + (values_mask & GDK_GC_SUBWINDOW)) + _gdk_gc_remove_drawable_clip (gc); + if (values_mask & GDK_GC_CLIP_X_ORIGIN) gc->clip_x_origin = values->clip_x_origin; if (values_mask & GDK_GC_CLIP_Y_ORIGIN) @@ -549,10 +561,10 @@ gdk_gc_set_clip_mask (GdkGC *gc, } /* Takes ownership of passed in region */ -void -_gdk_gc_set_clip_region_internal (GdkGC *gc, - GdkRegion *region, - gboolean reset_origin) +static void +_gdk_gc_set_clip_region_real (GdkGC *gc, + GdkRegion *region, + gboolean reset_origin) { GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); @@ -564,37 +576,54 @@ _gdk_gc_set_clip_region_internal (GdkGC *gc, _gdk_windowing_gc_set_clip_region (gc, region, reset_origin); } +/* Doesn't copy region, allows not to reset origin */ +void +_gdk_gc_set_clip_region_internal (GdkGC *gc, + GdkRegion *region, + gboolean reset_origin) +{ + _gdk_gc_remove_drawable_clip (gc); + _gdk_gc_set_clip_region_real (gc, region, reset_origin); +} + + /* returns old clip region */ void -_gdk_gc_intersect_clip_region (GdkGC *gc, - GdkRegion *region, - int offset_x, - int offset_y, - GdkRegion **old_clip_region) +_gdk_gc_add_drawable_clip (GdkGC *gc, + guint32 region_tag, + GdkRegion *region, + int offset_x, + int offset_y) { GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); - GdkRegion *old_clip; - gboolean free; - old_clip = priv->clip_region; + g_assert (priv->old_clip_region == NULL); + + priv->region_tag_applied = region_tag; + priv->old_clip_region = priv->clip_region; region = gdk_region_copy (region); - if (offset_x != 0 || offset_y != 0) gdk_region_offset (region, offset_x, offset_y); priv->clip_region = region; - if (old_clip) - gdk_region_intersect (region, old_clip); + if (priv->old_clip_region) + gdk_region_intersect (region, priv->old_clip_region); - if (old_clip_region) - *old_clip_region = old_clip; - else - gdk_region_destroy (old_clip); - _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE); - - return old_clip; +} + +void +_gdk_gc_remove_drawable_clip (GdkGC *gc) +{ + GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc); + + if (priv->region_tag_applied) + { + _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE); + priv->old_clip_region = NULL; + priv->region_tag_applied = 0; + } } /** @@ -614,12 +643,14 @@ gdk_gc_set_clip_rectangle (GdkGC *gc, g_return_if_fail (GDK_IS_GC (gc)); + _gdk_gc_remove_drawable_clip (gc); + if (rectangle) region = gdk_region_rectangle (rectangle); else region = NULL; - _gdk_gc_set_clip_region_internal (gc, region, TRUE); + _gdk_gc_set_clip_region_real (gc, region, TRUE); } /** @@ -639,12 +670,14 @@ gdk_gc_set_clip_region (GdkGC *gc, g_return_if_fail (GDK_IS_GC (gc)); + _gdk_gc_remove_drawable_clip (gc); + if (region) copy = gdk_region_copy (region); else copy = NULL; - _gdk_gc_set_clip_region_internal (gc, copy, TRUE); + _gdk_gc_set_clip_region_real (gc, copy, TRUE); } /** @@ -945,6 +978,16 @@ gdk_gc_copy (GdkGC *dst_gc, dst_priv->clip_region = gdk_region_copy (src_priv->clip_region); else dst_priv->clip_region = NULL; + + dst_priv->region_tag_applied = src_priv->region_tag_applied; + + if (dst_priv->old_clip_region) + gdk_region_destroy (dst_priv->old_clip_region); + + if (src_priv->old_clip_region) + dst_priv->old_clip_region = gdk_region_copy (src_priv->old_clip_region); + else + dst_priv->old_clip_region = NULL; dst_priv->fill = src_priv->fill; diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 995f3bf455..c9d537828d 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -293,11 +293,12 @@ GdkPixmap *_gdk_gc_get_tile (GdkGC *gc); GdkBitmap *_gdk_gc_get_stipple (GdkGC *gc); guint32 _gdk_gc_get_fg_pixel (GdkGC *gc); guint32 _gdk_gc_get_bg_pixel (GdkGC *gc); -void _gdk_gc_intersect_clip_region (GdkGC *gc, - GdkRegion *region, - int offset_x, - int offset_y, - GdkRegion **old_region); +void _gdk_gc_add_drawable_clip (GdkGC *gc, + guint32 region_tag, + GdkRegion *region, + int offset_x, + int offset_y); +void _gdk_gc_remove_drawable_clip (GdkGC *gc); void _gdk_gc_set_clip_region_internal (GdkGC *gc, GdkRegion *region, gboolean reset_origin); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 5d9b812a80..7043b8385d 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -69,6 +69,7 @@ struct _GdkWindowPaint gint y_offset; cairo_surface_t *surface; guint uses_implicit : 1; + guint32 region_tag; }; /* Global info */ @@ -234,6 +235,14 @@ static gpointer parent_class = NULL; static const cairo_user_data_key_t gdk_window_cairo_key; +static guint32 +new_region_tag (void) +{ + static guint32 tag = 0; + + return ++tag; +} + GType gdk_window_object_get_type (void) { @@ -509,6 +518,7 @@ recompute_visible_regions_internal (GdkWindowObject *private, if (private->clip_region) gdk_region_destroy (private->clip_region); private->clip_region = new_clip; + private->clip_tag = new_region_tag (); private->clip_region_with_children = gdk_region_copy (private->clip_region); remove_child_area (private, NULL, private->clip_region_with_children); @@ -1925,17 +1935,19 @@ gdk_window_begin_paint_region (GdkWindow *window, implicit_paint = impl_window->implicit_paint; paint = g_new (GdkWindowPaint, 1); + paint->region = gdk_region_copy (region); + paint->region_tag = new_region_tag (); + if (implicit_paint) { int width, height; - + paint->uses_implicit = TRUE; paint->pixmap = g_object_ref (implicit_paint->pixmap); paint->x_offset = -private->abs_x + implicit_paint->x_offset; paint->y_offset = -private->abs_y + implicit_paint->y_offset; - paint->region = gdk_region_copy (region); gdk_region_intersect (paint->region, private->clip_region_with_children); - + /* It would be nice if we had some cairo support here so we could set the clip rect on the cairo surface */ width = private->abs_x + private->width; @@ -1943,9 +1955,6 @@ gdk_window_begin_paint_region (GdkWindow *window, paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl, width, height); - if (paint->surface) - cairo_surface_set_device_offset (paint->surface, - - paint->x_offset, - paint->y_offset); /* Mark the region as valid on the implicit paint */ gdk_region_offset (paint->region, private->abs_x, private->abs_y); @@ -1955,19 +1964,18 @@ gdk_window_begin_paint_region (GdkWindow *window, else { paint->uses_implicit = FALSE; - paint->region = gdk_region_copy (region); paint->x_offset = clip_box.x; paint->y_offset = clip_box.y; paint->pixmap = gdk_pixmap_new (window, MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1); - paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap); - cairo_surface_set_device_offset (paint->surface, - - paint->x_offset, - paint->y_offset); } + + if (paint->surface) + cairo_surface_set_device_offset (paint->surface, + -paint->x_offset, -paint->y_offset); - for (list = private->paint_stack; list != NULL; list = list->next) { GdkWindowPaint *tmp_paint = list->data; @@ -2264,8 +2272,7 @@ gdk_window_get_internal_paint_info (GdkWindow *window, static void setup_clip_for_draw (GdkDrawable *drawable, GdkGC *gc, - int old_clip_x, int old_clip_y, - GdkRegion **old_clip_region) + int old_clip_x, int old_clip_y) { GdkWindowObject *private = (GdkWindowObject *)drawable; GdkRegion *clip; @@ -2275,27 +2282,27 @@ setup_clip_for_draw (GdkDrawable *drawable, else clip = private->clip_region; - _gdk_gc_intersect_clip_region (gc, clip, - /* If there was a clip origin set appart from the - * window offset, need to take that into consideration */ - -old_clip_x, -old_clip_y, - old_clip_region); + _gdk_gc_add_drawable_clip (gc, + private->clip_tag, + clip, + /* If there was a clip origin set appart from the + * window offset, need to take that into consideration */ + -old_clip_x, -old_clip_y); } static void setup_clip_for_paint (GdkDrawable *drawable, GdkWindowPaint *paint, GdkGC *gc, - int old_clip_x, int old_clip_y, - GdkRegion **old_clip_region) + int old_clip_x, int old_clip_y) { - _gdk_gc_intersect_clip_region (gc, - /* This includes the window clip */ - paint->region, - /* If there was a clip origin set appart from the - * window offset, need to take that into consideration */ - -old_clip_x, -old_clip_y, - old_clip_region); + _gdk_gc_add_drawable_clip (gc, + paint->region_tag, + /* This includes the window clip */ + paint->region, + /* If there was a clip origin set appart from the + * window offset, need to take that into consideration */ + -old_clip_x, -old_clip_y); } @@ -2322,23 +2329,21 @@ setup_clip_for_paint (GdkDrawable *drawable, } #define SETUP_PAINT_GC_CLIP(gc) \ - GdkRegion *old_clip_region; \ if (paint->uses_implicit) \ setup_clip_for_paint (drawable, paint, gc, old_clip_x, \ - old_clip_y, &old_clip_region); + old_clip_y); #define RESTORE_PAINT_GC_CLIP(gc) \ if (paint->uses_implicit) \ - _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE); + _gdk_gc_remove_drawable_clip (gc); #define SETUP_DIRECT_GC_CLIP(gc) \ - GdkRegion *old_clip_region; \ gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\ - setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region); + setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y); #define RESTORE_DIRECT_GC_CLIP(gc) \ - _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE); + _gdk_gc_remove_drawable_clip (gc); static GdkGC * gdk_window_create_gc (GdkDrawable *drawable, diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index ec3f67ac39..7a628b58c7 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -328,6 +328,7 @@ struct _GdkWindowObject int abs_x, abs_y; /* Absolute offset in impl */ gint width, height; + guint32 clip_tag; GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */ GdkRegion *clip_region_with_children; /* Clip region in window coords */ GdkColormap *colormap; -- 2.30.2